package com.yuoj.yuojcodesandbox.dao;



import com.github.dockerjava.api.DockerClient;
import com.github.dockerjava.api.async.ResultCallback;
import com.github.dockerjava.api.command.*;
import com.github.dockerjava.api.model.HostConfig;
import com.github.dockerjava.api.model.Image;
import com.github.dockerjava.api.model.PullResponseItem;
import com.github.dockerjava.api.model.Statistics;
import com.github.dockerjava.core.command.ExecStartResultCallback;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Repository;

import javax.annotation.Resource;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author 刘渠好
 * @since 2025/3/29 16:26
 * java操作docker dao
 */
//@Repository
@Slf4j
public class DockerDao {
    //获取默认的docker客户端

    @Resource
    private DockerClient dockerClient;


    //拉取镜像
    public void pullImage(String imageName) {

        //拉取镜像
        PullImageCmd pullImageCmd = dockerClient.pullImageCmd(imageName);

        try(PullImageResultCallback pullImageResultCallback = new PullImageResultCallback() {
            @Override
            public void onNext(PullResponseItem item) {
                log.info("拉取镜像==>{}",item.getStatus());
                super.onNext(item);
            }
        }){
            pullImageCmd
                    .exec(pullImageResultCallback)
                    //等待执行结束之后，继续往下执行
                    .awaitCompletion();
            log.info("拉取{}镜像成功!",imageName);
        } catch(Exception e) {
            log.error("拉取{}镜像失败!",imageName,e);
            throw new RuntimeException("拉取镜像失败！");
        }
    }

    //创建容器
    public CreateContainerResponse createContainer(String imageName, HostConfig hostConfig){
        return   dockerClient.createContainerCmd(imageName)
                .withTty(true)
                .withNetworkDisabled(false)
                .withAttachStdin(true)
                .withAttachStdout(true)
                .withAttachStderr(true)
                .withReadonlyRootfs(true)
                .withHostConfig(hostConfig)
                .exec();

    }

    //启动容器
    public void startContainer(String containerId){
        dockerClient
                .startContainerCmd(containerId)
                .exec();
    }

    //创建执行命令
    public ExecCreateCmdResponse CreateExecuteCmd(String containerId,String... cmd){
        return dockerClient
                .execCreateCmd(containerId)
                .withAttachStdout(true)
                .withAttachStderr(true)
                .withAttachStdin(true)
                .withTty(false)
                .withCmd(cmd)
                .exec();

    }

    //执行启动(无时间限制)
    public void  execStart(String execId, ExecStartResultCallback startResultCallback ){
        try {
            dockerClient
                    .execStartCmd(execId)
                    .withDetach(false)
                    .exec(startResultCallback)
                    .awaitCompletion();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    //执行启动(有时间限制)
    public void  execStart(String execId, ExecStartResultCallback startResultCallback,
                           long timeout, TimeUnit timeUnit){
        try {
            dockerClient
                    .execStartCmd(execId)
                    .withDetach(false)
                    .exec(startResultCallback)
                    .awaitCompletion(timeout,timeUnit);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    //获取容器状态
    public ResultCallback<Statistics> stats(String containerId, ResultCallback<Statistics> resultCallback){
        return dockerClient
                .statsCmd(containerId)
                .exec(resultCallback);
    }

    //删除容器
    public void  deleteContainer(String containerId){
        dockerClient.removeContainerCmd(containerId)
                .withForce(true)
                .exec();
    }

    //删除镜像
    public void deleteImage(String imageName){
        dockerClient.removeImageCmd(imageName)
                .withForce(true)
                .exec();
    }

    //查看镜像列表
    public List<String> getImageList(){
        List<Image> imageList = dockerClient.listImagesCmd()
                .withShowAll(true)
                .exec();
        List<String[]> collect = imageList.stream().map(Image::getRepoTags).collect(Collectors.toList());
        List<String> imageTags = new LinkedList<> ();
        for (String[] image : collect) {
            imageTags.add(image[0]);
        }
        return imageTags;
    }


}
